package com.java.base.io.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AIOServer {

    static Logger logger = Logger.getLogger(AIOServer.class.getSimpleName());

    static {
        logger.setLevel(Level.INFO);
    }

    public static void main(String[] args) throws IOException {
//        ExecutorService executorService = Executors.newCachedThreadPool();
        //initialSize代表使用几个线程池处理
//        AsynchronousChannelGroup threadGroup = AsynchronousChannelGroup.withCachedThreadPool(executorService, 2);

        AsynchronousServerSocketChannel serverSocketChannel =
                AsynchronousServerSocketChannel.open();
//                AsynchronousServerSocketChannel.open(threadGroup);
        serverSocketChannel.bind(new InetSocketAddress(0xcccc));
        serverSocketChannel.accept(null, new AIOAccept(serverSocketChannel));

        logger.info("Start...");
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }


    public static class AIOAccept implements CompletionHandler<AsynchronousSocketChannel, Object> {

        AsynchronousServerSocketChannel serverSocketChannel;

        public AIOAccept(AsynchronousServerSocketChannel serverSocketChannel) {
            this.serverSocketChannel = serverSocketChannel;
        }

        @Override
        public void completed(AsynchronousSocketChannel socketChannel, Object attachment) {
            serverSocketChannel.accept(attachment, this);

            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            socketChannel.read(byteBuffer, byteBuffer, new AIORead(socketChannel));
        }

        @Override
        public void failed(Throwable exc, Object attachment) {
            logger.warning(exc.getMessage());
        }
    }


    public static class AIORead implements CompletionHandler<Integer, ByteBuffer> {
        AsynchronousSocketChannel socketChannel;

        public AIORead(AsynchronousSocketChannel socketChannel) {
            this.socketChannel = socketChannel;
        }

        @Override
        public void completed(Integer result, ByteBuffer buffer) {
            buffer.flip();
            if (result <= 0) {
                try {
                    socketChannel.close();
                    return;
                } catch (IOException e) {
                    logger.warning(e.toString());
                    return;
                }
            }
            String msg = Thread.currentThread().getName() + " msg=" + new String(buffer.array(), 0, result);
            logger.info(msg);
            buffer.clear();
            socketChannel.write(ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8)));
            socketChannel.read(buffer, buffer, this);
        }

        @Override
        public void failed(Throwable exc, ByteBuffer buffer) {
            logger.warning(exc.getMessage());
        }
    }


   /* public static void read(AsynchronousSocketChannel socketChannel) {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        socketChannel.read(buffer, buffer, new CompletionHandler<>() {
            @Override
            public void completed(Integer result, ByteBuffer buffer) {
                buffer.flip();
                String msg = Thread.currentThread().getName() + " msg=" + new String(buffer.array(), 0, result);
                logger.info(msg);
                socketChannel.write(ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8)));
                read(socketChannel);
            }

            @Override
            public void failed(Throwable exc, ByteBuffer buffer) {
                logger.warning(exc.getMessage());
            }
        });
    }*/

}
